package com.cloudkinto.appletservice.finance.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.appletservice.finance.AppletRechargeRecordService;
import com.cloudkinto.appletservice.finance.vo.AppletRechagregDetaiRes;
import com.cloudkinto.common.DicBusinessItemConstant;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.exception.BizExceptionI18;
import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.CompanyAccountDao;
import com.cloudkinto.dao.ExchangeRateDao;
import com.cloudkinto.dao.RechargeRecordDao;
import com.cloudkinto.dao.RechargeTypeDao;
import com.cloudkinto.entity.CompanyAccountDo;
import com.cloudkinto.entity.ExchangeRateDo;
import com.cloudkinto.entity.RechargeRecordDo;
import com.cloudkinto.entity.RechargeTypeDo;
import com.cloudkinto.service.email.MailSenderService;
import com.cloudkinto.service.file.FileService;
import com.cloudkinto.service.finance.vo.IdAndNameEntity;
import com.cloudkinto.service.finance.vo.RechargeAddReq;
import com.cloudkinto.service.finance.vo.RechargeRecordRes;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author ding
 * @since 2020-06-10
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class AppletRechargeRecordServiceImpl extends ServiceImpl<RechargeRecordDao, RechargeRecordDo> implements AppletRechargeRecordService {
    private static final String MONEY_TYPE_RMB = "0";
    private static final String MONEY_TYPE_JP = "1";
    private static final String MONEY_TYPE_US = "2";
    @Autowired
    private RechargeRecordDao dao;
    @Autowired
    private RechargeTypeDao rechargeTypeDao;
    @Autowired
    private CompanyAccountDao accountDao;
    @Autowired
    private ExchangeRateDao exchangeRateDao;
    @Autowired
    private FileService fileService;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private MailSenderService mailSenderService;

    @Override
    public SingleResult addInit(Long companyId) {
        LambdaQueryWrapper<CompanyAccountDo> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CompanyAccountDo::getCompanyId, companyId);
        CompanyAccountDo companyAccountDo = accountDao.selectOne(wrapper);
        Map<String, Double> amount = new HashMap<>();
        if (companyAccountDo == null) {
            amount.put("balance", 0d);
        } else {
            amount.put("balance", companyAccountDo.getCompanyAccount());
        }
        List<RechargeTypeDo> rechargeTypeDoList = rechargeTypeDao.selectList(new QueryWrapper<>());
        ExchangeRateDo exchangeRate = getExchangeRate();
        Map addInit = new HashMap();
        addInit.put("accountAmount", amount);
        if (exchangeRate != null)
            addInit.put("rate", exchangeRate.getRate());
        addInit.put("payType", rechargeTypeDoList);
        List<IdAndNameEntity> idAndNameEntities = new ArrayList<>();

        idAndNameEntities.add(new IdAndNameEntity(MONEY_TYPE_RMB, "人民币"));

        idAndNameEntities.add(new IdAndNameEntity(MONEY_TYPE_JP, "日币"));

        addInit.put("moneyType", idAndNameEntities);
        return SingleResult.success(addInit);
    }

    @Override
    public Object add(RechargeAddReq rechargeAddReq, Long companyId, Long userId) {
//        SingleResult singleResult = fileService.uploadTempFile(file, userId);
        RechargeRecordDo entityDo = new RechargeRecordDo();
        entityDo.setId(System.currentTimeMillis());
        entityDo.setRechargeTypeId(Long.parseLong(rechargeAddReq.getPayType()));
        RechargeTypeDo rechargeTypeDo = rechargeTypeDao.selectById(Long.parseLong(rechargeAddReq.getPayType()));
        if (rechargeTypeDo == null) throw new BizExceptionI18("error.charge.type");
        entityDo.setRechargeAccount(1L);//指定充值账号
        ExchangeRateDo exchangeRate = getExchangeRate();
        if (MONEY_TYPE_RMB.equals(rechargeTypeDo.getCurrency())) {//充值为人民币时选择为0
            //todo 实时汇率
            double amountJP = rechargeAddReq.getAmount() / exchangeRate.getRate() ;
            entityDo.setAmountJpy(new BigDecimal(amountJP).setScale(0, RoundingMode.HALF_UP).doubleValue());
            entityDo.setAmountRmb(rechargeAddReq.getAmount());
        } else {
            double amountRMB = rechargeAddReq.getAmount()  * exchangeRate.getRate();
            entityDo.setAmountRmb(new BigDecimal(amountRMB).setScale(2, RoundingMode.HALF_UP).doubleValue());
            entityDo.setAmountJpy(rechargeAddReq.getAmount());
        }
        entityDo.setCompanyId(companyId);
        entityDo.setCertificateImageFileId(rechargeAddReq.getFileId() == null ? null : Long.parseLong(rechargeAddReq.getFileId()));
        entityDo.setTips(rechargeAddReq.getTips());
//        BeanUtils.copyProperties(req, entityDo);
        handlerAddBefore(entityDo, userId);
        dao.insert(entityDo);
        threadPoolTaskExecutor.execute(() -> {
            handlerAddAfter(entityDo);
        });
        return null;
    }

    private ExchangeRateDo getExchangeRate() {
        QueryWrapper exrateWrapper = new QueryWrapper();
        exrateWrapper.orderByDesc("id");
        exrateWrapper.eq("type", DicBusinessItemConstant.currency_jpy);
        exrateWrapper.last("limit 1");
        return exchangeRateDao.selectOne(exrateWrapper);
    }

    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(RechargeRecordDo entityDo, Long userId) {
        entityDo.setCreateBy(userId);
        entityDo.setCreateTime(new Date());
        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
    }

    //将新增的do转换成要返回的实体
    private Object handlerAddAfter(RechargeRecordDo entityDo) {
        //文件操作
        fileService.uploadFile(entityDo.getCertificateImageFileId());
        threadPoolTaskExecutor.execute(() -> {
            RechargeTypeDo rechargeTypeDo = rechargeTypeDao.selectById(entityDo.getRechargeTypeId());
            mailSenderService.sendEmail("您有新的充值申请单需要审核", entityDo.getCompanyId() +
                    "<br>充值人民币" + entityDo.getAmountRmb() + "<br>充值方式" + rechargeTypeDo.getTypeName() + "(" + rechargeTypeDo.getAccountName() + ")"
                    + "，请尽快审核,备注：<br>" + entityDo.getTips() + "充值凭证<br>"
                    + fileService.getFilePath(entityDo.getCertificateImageFileId()), SysConstant.cloudkintEmail);
        });
        return null;
    }

    @Override
    public SingleResult updateInit(Long id) {
        return SingleResult.success("");
    }

    @Override
    public Object update(Object req, Long userId) {
        /*RechargeRecordDo entityDo = dao.selectById(req.getId());
        BeanUtils.copyProperties(req, entityDo);
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return handlerUpdateAfter(entityDo);*/
        return null;
    }

    //编辑校验
    private void updateCheck(Object req) {

    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(RechargeRecordDo entityDo, Long userId) {
//        entityDo.setUpdateBy(userId);
//        entityDo.setUpdateTime(new Date());
    }

    //做修改之后要执行的业务定制处理
    private Object handlerUpdateAfter(RechargeRecordDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public int delete(Long id, Long userId) {
        RechargeRecordDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);
        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(RechargeRecordDo entityDo, Long userId) {
        entityDo.setDeleteBy(userId);
        entityDo.setDeleteTime(new Date());
    }

    @Override
    public AppletRechagregDetaiRes detail(Long id) {
        RechargeRecordDo entityDo = dao.selectById(id);
        AppletRechagregDetaiRes res = new AppletRechagregDetaiRes();
        BeanUtils.copyProperties(entityDo, res);
        return handlerDetailAfter(entityDo, res);
    }

    //查询明细之后要执行的业务定制处理
    private AppletRechagregDetaiRes handlerDetailAfter(RechargeRecordDo recordDo, AppletRechagregDetaiRes recordRes) {

        BeanUtils.copyProperties(recordDo, recordRes);
        recordRes.setAmountJpy("" + recordDo.getAmountJpy());
        recordRes.setAmountRmb("¥" + recordDo.getAmountRmb());
        if (recordDo.getRechargeTypeId() == 0) {//type  0 是筋斗云后台充值
            recordRes.setRechargeType("后台充值");
        } else {
            RechargeTypeDo rechargeTypeDo = rechargeTypeDao.selectById(recordDo.getRechargeTypeId());
            if (rechargeTypeDo == null) {
                recordRes.setRechargeType("后台充值");
            } else {
                recordRes.setRechargeType(rechargeTypeDo.getTypeName());
            }
        }
        recordRes.setStatus(getStatusMap().get(recordDo.getStatus()));
        return recordRes;
    }

    private Map<String, String> getStatusMap() {
        Map<String, String> statusMap = new HashMap();
        //0 待审核  1充值成功 2充值取消
        statusMap.put("0", "等待审核");
        statusMap.put("1", "充值成功");
        statusMap.put("2", "充值取消");
        return statusMap;
    }

    @Override
    public SingleResult pageInit() {
        List<IdAndNameEntity> mapList = new ArrayList<>();
        //0 待审核  1充值成功 2充值取消
        ;
        mapList.add(new IdAndNameEntity(0, "等待审核"));
        mapList.add(new IdAndNameEntity(1, "充值成功"));
        mapList.add(new IdAndNameEntity(2, "充值取消"));
        return SingleResult.success(mapList);
    }

    @Override
    public List<RechargeRecordRes> getList(Map<String, String> map) {
        QueryWrapper<RechargeRecordDo> wrapper = queryBuild(map);
        List<RechargeRecordDo> list = this.list(wrapper);
        List<RechargeRecordRes> result = handlerListAfter(list);
        return result;
    }

    @Override
    public PageResult<RechargeRecordRes> getListPage(Map<String, String> map) {
        QueryWrapper<RechargeRecordDo> wrapper = queryBuild(map);
        IPage<RechargeRecordDo> page = pageInit(map);
        page = this.page(page, wrapper);
        List<RechargeRecordRes> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        Map<String, String> map1 = new HashMap<>();
        long total = dao.selectSumAmount(map);
        map1.put("total", new BigDecimal(total).toPlainString());
        result.setMapInfo(map1);
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<RechargeRecordRes> handlerListAfter(List<RechargeRecordDo> list) {
        Map<String, String> payTypeMap = new HashMap();
        //0支付宝 1对公转账  对私转账 3 微信 4 系统充值
        payTypeMap.put("0", "支付宝");
        payTypeMap.put("1", "对公转账");
        payTypeMap.put("2", "对私转账");
        payTypeMap.put("3", "微信");
        payTypeMap.put("4", "系统充值");

        List<RechargeRecordRes> result = new ArrayList<>();
        for (RechargeRecordDo recordDo : list) {
            RechargeRecordRes recordRes = new RechargeRecordRes();
            BeanUtils.copyProperties(recordDo, recordRes);
            recordRes.setAmountJp("" + recordDo.getAmountJpy());
            recordRes.setAmountRmb("¥" + recordDo.getAmountRmb());
            if (recordDo.getRechargeTypeId() == 0) {//type  0 是筋斗云后台充值
                recordRes.setPayType("后台充值");
            } else {
                RechargeTypeDo rechargeTypeDo = rechargeTypeDao.selectById(recordDo.getRechargeTypeId());
                if (rechargeTypeDo == null) {
                    recordRes.setPayType("后台充值");
                } else {
                    recordRes.setPayType(rechargeTypeDo.getTypeName());
                }
            }
            recordRes.setStatus(getStatusMap().get(recordDo.getStatus()));
//            recordRes.setCertificateImagePath();
            result.add(recordRes);
        }
        return result;
    }

    private IPage<RechargeRecordDo> pageInit(Map<String, String> map) {
        IPage<RechargeRecordDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<RechargeRecordDo> queryBuild(Map<String, String> map) {
        QueryWrapper<RechargeRecordDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("startDate"))) {
            wrapper.ge("create_time", map.get("startDate"));
        }
        if (StringUtils.isNotBlank(map.get("endDate"))) {
            wrapper.le("create_time", map.get("endDate"));
        }
        if (StringUtils.isNotBlank(map.get("status"))) {
            wrapper.eq("status", map.get("status"));
        }
        if (StringUtils.isNotBlank(map.get("companyId"))) {
            wrapper.eq("company_id", map.get("companyId"));
        }
        wrapper.orderByDesc("id");
        return wrapper;
    }


}
